package terrain;

import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
//import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import system.Camera;

import javax.microedition.khronos.opengles.GL10;

public class BruteForce_Terrain extends Terrain {
	private static ShortBuffer[]	m_aIndicates;// = { 0 , 1 , 2};
	private FloatBuffer 		m_fbVertexBuffer;
	private FloatBuffer 		m_fbColorBuffer;
	private FloatBuffer			m_fbTexCoords;
	
	float[] twoLastVers;
	float[] twoLastCols;
	
	
	// Override from base function
	// initialize for vertexbuffer , indicatebuffer and colorbuffer
	@Override
	public boolean LoadHeightMapFromRawFile (InputStream is, int Width, int Height){
		super.LoadHeightMapFromRawFile(is, Width, Height);
		return IniValueForBuffers();
	}
	
	@Override
	public boolean LoadHeightMapFromBitmap (InputStream is, int Width, int Height){
		super.LoadHeightMapFromBitmap(is, Width, Height);
		return IniValueForBuffers();
	}
	
	@Override
	public boolean LoadHeightMapFromBitmap (InputStream is){
		super.LoadHeightMapFromBitmap(is);
		return IniValueForBuffers();
	}
	
	
	private boolean IniValueForBuffers(){
		ByteBuffer vbb = ByteBuffer.allocateDirect(m_iWidth*m_iHeight* 3 * 4);	// sizeof(float) = 4
		vbb.order(ByteOrder.nativeOrder());
		m_fbVertexBuffer = vbb.asFloatBuffer();

		m_aIndicates = new ShortBuffer[m_iWidth];
		for (int i = 0; i < m_iWidth; ++i){
			ByteBuffer ibb = ByteBuffer.allocateDirect(m_iWidth* 2*2);	
			ibb.order(ByteOrder.nativeOrder());
			m_aIndicates[i] = ibb.asShortBuffer();
		}

		ByteBuffer cbb = ByteBuffer.allocateDirect(m_iHeight*m_iWidth* 4 * 4);	// sizeof(float) = 4
		cbb.order(ByteOrder.nativeOrder());
		m_fbColorBuffer = cbb.asFloatBuffer();
		
		ByteBuffer tbb = ByteBuffer.allocateDirect(m_iHeight*m_iWidth*2 * 4);	// sizeof(float) = 4
		tbb.order(ByteOrder.nativeOrder());
		m_fbTexCoords = tbb.asFloatBuffer();
		

		// init value for variants
		
		float lastX = 0f;
		float lastZ = 0f;
		float tempColor;
		MakeSmooth(0.75f);
		float _halfWidth = m_iHalfWidth*m_fScalePosition;
		float _halfHeight = m_iHalfHeight*m_fScalePosition;
		
		m_fbColorBuffer.position(0);
		m_fbVertexBuffer.position(0);
		try{
		for (int z = -m_iHalfHeight; z < m_iHalfHeight; ++z){
			lastX = 0;
			for (int x = -m_iHalfWidth; x <  m_iHalfWidth; ++x){				
				// put position
				m_fbVertexBuffer.put(lastX - _halfWidth);
				m_fbVertexBuffer.put(GetScaleHeightAtPoint(x,z));
//				m_fbVertexBuffer.put(0);
				m_fbVertexBuffer.put(lastZ - _halfHeight);
				
				m_fbTexCoords.put(lastX - _halfWidth);
//				m_fbTexCoords.put(GetScaleHeightAtPoint(x,z));
//				m_fbVertexBuffer.put(0);
				m_fbTexCoords.put(lastZ - _halfHeight);
							
				// put color
				tempColor = ((GetTrueHeightAtPoint(x,z))/255f);
				m_fbColorBuffer.put(tempColor);
				m_fbColorBuffer.put(tempColor);
				m_fbColorBuffer.put(tempColor);
				m_fbColorBuffer.put(1f);
				
				lastX += m_fScalePosition;	
			}
			lastZ += m_fScalePosition;
		}
		}catch(Exception e){
			int a= 2;
			a++;
		}
			
		for (int z = 0; z < m_iHeight; ++z){
			m_aIndicates[z].position(0);
			for (int x = 0; x <  m_iWidth; ++x){
				m_aIndicates[z].put((short)(z*m_iHeight + x));
				m_aIndicates[z].put((short)((z+1)*m_iHeight + x));
			}
			m_aIndicates[z].position(0);
		}
		
		m_fTranslateY = -GetScaleHeightAtPoint(0, 0) - 2f;

		return true;
	}
	
	// ----------------------------------------
	// Name:			Render - public
	// Description:		Render the terrain from height-map
	// Arguments:		gl: a GL object
	// Return:			None
	//-----------------------------------------
	@Override
	public void Render(GL10 gl) {
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		m_fbTexCoords.position(0);
		
		gl.glPushMatrix();
		gl.glLoadIdentity();
		gl.glEnable(GL10.GL_CCW);
		if (m_texture != null){
			m_texture.Binding(gl);
		}
		gl.glShadeModel(GL10.GL_SMOOTH);					   // use smooth shading
		gl.glEnable(GL10.GL_DEPTH_TEST);					   // hidden surface removal
		gl.glEnable(GL10.GL_CULL_FACE);						   // do not calculate inside of poly's
//		gl.glFrontFace(GL10.GL_CCW);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, m_fbTexCoords);
		gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
		gl.glEnable(GL10.GL_BLEND);
		gl.glEnable(GL10.GL_ALPHA_TEST);
		gl.glAlphaFuncx(GL10.GL_GREATER,0);
		gl.glDisable(GL10.GL_ALPHA_TEST);
		
		int beginZ, endZ, beginIndicate, endIndicate;
		float beta = (Camera.GetBeta() %  360);
		if ( beta >= 0 && beta < 90 ){
			beginZ = m_iHalfHeight;
		}
//		gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
		//gl.glPointSize(2f);
		gl.glTranslatef(m_fTranslateX, m_fTranslateY, m_fTranslateZ);
				gl.glVertexPointer(3, GL10.GL_FLOAT, 0, m_fbVertexBuffer);
//				gl.glColorPointer(4, GL10.GL_FLOAT, 0, m_fbColorBuffer);
				for (int z = 0; z < m_iHeight - 1; ++z){
					m_fbVertexBuffer.position(0);
					m_fbColorBuffer.position(0);
					m_aIndicates[z].position(0);
						gl.glVertexPointer(3, GL10.GL_FLOAT, 0, m_fbVertexBuffer);
						
//						gl.glColorPointer(4, GL10.GL_FLOAT, 0, m_fbColorBuffer);
						gl.glDrawElements(GL10.GL_TRIANGLE_STRIP,2*m_iWidth, GL10.GL_UNSIGNED_SHORT, m_aIndicates[z]);
					m_aIndicates[z].position(0);
				}
				m_fbVertexBuffer.position(0);
//				m_fbColorBuffer.position(0);
		if (m_texture != null){
			m_texture.Unbinding(gl);
		}
//		gl.glEnable(GL10.GL_BLEND);
//
//		// enable read-only depth buffer
//		gl.glDepthMask(false);
//
//		// set the blend function to what we use for transparency
//		gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
//
//		// set back to normal depth buffer mode (writable)
//		gl.glDepthMask(true);
//
//		// disable blending
//		gl.glDisable(GL10.GL_BLEND);

//		gl.glFlush();
		gl.glPopMatrix();
		gl.glMatrixMode(GL10.GL_PROJECTION);
	}
	

}
